<?php

/**
 * This class is used as a stream to load files dynamically
 * when using the <xsl:import> or <xsl:include> tags.
 * The registered stream calls a user defined function
 * which in turns returns the full path to the file to
 * be imported/included.
 *
 * Usage:
 *
 * 1. In some php file, before xsl processing, insert something like:
 * <code>
 * //load class
 * require_once('ImportStream.php');
 * //register import function (must be callable - class/method or function)
 * ImportStream::registerImportHandler('getXsl');
 * //register new stream ( 'var' is just an example, use whatever)
 * stream_wrapper_register('var', 'ImportStream');
 * //define a function - $path is defined in xsl:import call below
 * function getXsl($path)
 * {        
 *     //here do logic to figure out file
 *     $myFile = '/my/preferred/file.xsl';
 *     //return desired full path to xsl file   
 *     return($myFile);
 * }
 * </code>
 *
 * 2. In the xsl file
 * <code>
 * <xsl:stylesheet version="1.0" 
 *   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 *   xmlns:var="http://php.net/xsl">
 * <xsl:import href="var://path"/>
 * <!-- note that 'path' gets passed as argument to getXsl() function -->
 * </code>
 *
 * Notes: Using this method, EVERY path will have the 'path' appended to it. It is up to
 * the function to deal with this. For absolute paths, you MUST use the file:// scheme to 
 * prevent this.
 * 
 * This file is getting deprecated very soon. 
 */
 
class ImportStream {

    /**
     * Hold an instance of the class
     *
     * @var     object   
     */
     
    static private $instance;
    
    
    /**
     * Import handler
     *
     * @var     mixed   
     */
     
    static private $importHandler;
    
     /**
     * Current file pointer position
     * 
     * @var     integer
     */
     
    var $position;
    
    
    /**
     * File handler
     * 
     * @var     reference
     */
     
    var $handler;
    
    /**
     * Stream function 
     * 
     * @see PHP function: stream_wrapper_register()
     */
    
    function stream_open($path, $mode, $options, &$opened_path) 
    {
   
        $url = parse_url($path);
        //$arg = $url['host'].$url['path'];
        $arg = $url['host'];
		
         //output handler defined?
        if(!is_null(self::$importHandler)) 
        {        
          
            $file = call_user_func(self::$importHandler, $arg);
        }
        
        
        $this->handler = fopen($file, 'rb');
        if(!$this->handler)
            return false;        
        
        $this->position = 0;
        return true;
    }
    
    
    /**
     * Stream function 
     * 
     * @see PHP function: stream_wrapper_register()
     */
    function stream_read($count) 
    {
        return fread($this->handler, $count);
       
        $this->position += $count;
        
    }
    
    
    /**
     * Stream function
     *
     * @see PHP function: stream_wrapper_register()
     */
    
    function stream_eof() 
    {
        return feof($this->handler);
    }
    
    
    /**
     * Stream function
     *
     * @see PHP function: stream_wrapper_register()
     */
    
    function stream_close() 
    {
        fclose($this->handler);
    }
    
    
    /**
     * Stream function
     *
     * @see PHP function: stream_wrapper_register()
     */
    function url_stat()
    {
        return array();
    }
      
    
    /**
     * Registers a function to be called to define imported file
     * 
     * This function is used to determine the path/filename of the xsl file to 
     * be imported or included in the xsl file...
     *
     * The handler should be a callable function or array of object/method as
     * defined in is_callable php function.  It should accept 1 arguments:
     * 1. The full URI as found in the href attribute of a xsl:import/include tag
     * minus the scheme part (see php function parse_url())
     *
     * This function should return a valid path to a valid xsl file
     *
     * @param  mixed        a function or an array of class=>method
     */
     
    static public function registerImportHandler($handler)
    {             
        if(is_callable($handler))   
            self::$importHandler = $handler;
        else
            NexistaException::init("ImportStream Import Handler is not callable!");
    }
    
    /**
     * Returns a class singleton.
     *
     * @return  object      class singleton instance
     */
     
    static public function singleton() 
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }
}


?>